using System;
using System.Collections.Generic;
using System.Linq;
using Urs.Core;
using Urs.Core.Caching;
using Urs.Core.Data;
using Urs.Data.Domain.Topics;

namespace Urs.Services.Topics
{
    public partial class TopicService : ITopicService
    {

        private const string TOPICCATEGORY_BY_ID_KEY = "Urs.topiccategory.id-{0}";
        private const string TOPICCATEGORY_PATTERN_KEY = "Urs.topiccategory.";

        #region Fields

        private readonly IRepository<Topic> _topicRepository;
        private readonly IRepository<TopicCategory> _topicCategoryRepository;
        private readonly ICacheManager _cacheManager;

        #endregion

        #region Ctor

        public TopicService(IRepository<Topic> topicRepository,
            IRepository<TopicCategory> topicCategoryRepository,
            ICacheManager cacheManager)
        {
            _topicRepository = topicRepository;
            _topicCategoryRepository = topicCategoryRepository;
            _cacheManager = cacheManager;
        }

        #endregion

        #region Topic

        public virtual void DeleteTopic(Topic topic)
        {
            if (topic == null)
                throw new ArgumentNullException("topic");

            _topicRepository.Delete(topic);

        }

        public virtual Topic GetTopicById(int topicId)
        {
            if (topicId == 0)
                return null;

            return _topicRepository.GetById(topicId);
        }

        public virtual Topic GetTopicBySystemName(string systemName)
        {
            if (String.IsNullOrEmpty(systemName))
                return null;

            var query = from t in _topicRepository.Table
                        where t.SystemName == systemName
                        select t;

            return query.FirstOrDefault();
        }

        public virtual IList<Topic> GetAllTopics()
        {
            var query = from t in _topicRepository.Table
                        orderby t.Id descending
                        select t;

            var topics = query.ToList();
            return topics;
        }

        public virtual IPagedList<Topic> GetAllTopics(string name, int pageIndex, int pageSize)
        {
            var query = _topicRepository.Table;

            if (!string.IsNullOrEmpty(name))
                query = query.Where(q => q.Title.StartsWith(name));

            query = query.Where(q => q.Published).OrderByDescending(b => b.Id);

            var topics = new PagedList<Topic>(query, pageIndex, pageSize);
            return topics;
        }

        public virtual void InsertTopic(Topic topic)
        {
            if (topic == null)
                throw new ArgumentNullException("topic");

            _topicRepository.Insert(topic);

        }

        public virtual void UpdateTopic(Topic topic)
        {
            if (topic == null)
                throw new ArgumentNullException("topic");

            _topicRepository.Update(topic);
        }

        #endregion

        #region Topic Category

        public virtual void DeleteTopicCategory(TopicCategory category)
        {
            if (category == null)
                throw new ArgumentNullException("category");

            _topicCategoryRepository.Delete(category);

            _cacheManager.RemoveByPattern(TOPICCATEGORY_PATTERN_KEY);

        }

        public virtual TopicCategory GetTopicCategoryById(int categoryId)
        {
            if (categoryId == 0)
                return null;

            string key = string.Format(TOPICCATEGORY_BY_ID_KEY, categoryId);
            return _cacheManager.Get(key, () =>
            {
                var n = _topicCategoryRepository.GetById(categoryId);
                return n;
            });
        }

        public virtual IPagedList<TopicCategory> GetAllTopicCategory(int pageIndex, int pageSize, bool showHidden = false)
        {
            var categories = GetAllTopicCategory(showHidden);
            return new PagedList<TopicCategory>(categories, pageIndex, pageSize);
        }

        public virtual IList<TopicCategory> GetAllTopicCategory(bool showHidden = false)
        {
            var query = _topicCategoryRepository.Table;
            if (!showHidden)
                query = query.Where(n => n.Published);
            query = query.OrderBy(b => b.DisplayOrder);

            var unsortedCategories = query.ToList();

            var sortedCategories = unsortedCategories.SortCategoriesForTree(0);
            return sortedCategories;
        }

        public virtual void InsertTopicCategory(TopicCategory category)
        {
            if (category == null)
                throw new ArgumentNullException("category");

            _topicCategoryRepository.Insert(category);

            _cacheManager.RemoveByPattern(TOPICCATEGORY_PATTERN_KEY);

        }

        public virtual void UpdateTopicCategory(TopicCategory category)
        {
            if (category == null)
                throw new ArgumentNullException("category");

            _topicCategoryRepository.Update(category);

            _cacheManager.RemoveByPattern(TOPICCATEGORY_PATTERN_KEY);
        }

        #endregion

    }
}
